function Build() {
	var me = this;
	var data;
	
	me.data = {
		name : 'New Build',
		
		/*
		 * Class Ids
		 * ---------
		 * Templar : 0
		 * Gladiator : 1
		 * 
		 */
		
		classId : null,
		class : null,
		
		/* Base Stats */
		
		baseStats : {
			hp : 0,
			defense : 0,
			parry : 0,
			dodge : 0,
			block : 0,
			blockAmount : 0
		},
		
		/* Group Buffs */
		
		groupBuffs : {
			
		},
		
		eh : {
			base : 0,
			selfBuffed : 0,
			groupBuffed : 0
		},
		
		ehDPB : {
			base : 0,
			selfBuffed : 0,
			groupBuffed : 0
		},
		
		monster : new Monster()
	};
	
	me.Events = {
		'ehchanged' : [],
		'ehdpbchanged' : [],
		'changed' : [],
		'namechanged' : [],
		'hpchanged' : [],
		'defensechanged' : [],
		'dodgechanged' : [],
		'parrychanged' : [],
		'blockchanged' : [],
		'blockamountchanged' : [],
		'selfbuffchanged' : [],
		'groupbuffchanged' : [],
		'monsterchanged' : []
	};
	
	me.initInternalListeners();
}

Build.prototype = new Event();

Build.prototype.init = function(data) {
	var me = this;
	
	me.Name = data.name;
	me.Hp = data.baseStats.hp;
	me.Defense = data.baseStats.defense;
	me.Block = data.baseStats.block;
	me.BlockAmount = data.baseStats.blockAmount;
	me.Dodge = data.baseStats.dodge;
	me.Parry = data.baseStats.parry;
};

Build.prototype.initInternalListeners = function() {
	
	var me = this;
	
	me.on('namechanged', function() {
		me.broadcast('changed');
	});
	
	me.on('classchanged, hpchanged, defensechanged, selfbuffchanged, groupbuffchanged', function() {
		me.refreshEh();
		me.broadcast('changed');
	});
	
	me.on('classchanged, hpchanged, defensechanged, dodgechanged, parrychanged, blockchanged, blockamountchanged, selfbuffchanged, groupbuffchanged', function() {
		me.refreshEh();
		me.refreshEhDPB();
		me.broadcast('changed');
	});
	
	me.Monster.on('changed', function() {
		me.refreshEh();
		me.refreshEhDPB();
		me.broadcast('changed');
	});
};

Build.prototype.refreshEh = function() {
	var me = this;

	//var totalHp = (me.Hp + me.Class.getModifier('hp', 'add')) * me.Class.getModifier('hp', 'mult');
	//var totalDefenseRate = (me.Defense + me.Class.getModifier('defenseRate', 'add')) * me.Class.getModifier('defenseRate', 'mult');
	
	me.data.eh.base = me.Hp + ((me.Defense / 10.0) * (me.Hp / parseFloat(me.Monster.HitAmount)));
	
	//me.data.eh.selfBuffed = totalHp * (1.0 + totalDefenseRate / 100.0);
	
	console.log('New EH...');
	console.log(me.data.eh);
	
	me.broadcast('ehchanged');
};

Build.prototype.refreshEhDPB = function() {
	var me = this;
	
	var blockPercent = (me.Block - me.Monster.Accuracy > 0) ? ((me.Block - me.Monster.Accuracy) / 10.0) : (0);
	
	me.data.ehDPB.base = me.data.eh.base * (1.0 + (blockPercent / 100.0) * (me.BlockAmount / 100.0));
	
	console.log('New EHDPB...');
	console.log(me.data.ehDPB);
	
	me.broadcast('ehdpbchanged');
};

Object.defineProperty(Build.prototype, "Name", {
	get : function() {
		return this.data.name;
	},
	set : function(value) {
		if (value != undefined && value != '') {
			this.data.name = value;
			this.broadcast('namechanged');
		}
	}
});

Object.defineProperty(Build.prototype, "ClassId", {
	get : function() {
		return this.data.classId;
	},
	set : function(value) {
		var me = this;
		
		if (value != undefined && value !== '') {
			this.data.classId = parseInt(value);
			
			if (this.data.classId != NaN) {
				
				switch (this.data.classId) {
					case 0:
						this.data.class = new Templar();
						break;
					case 1:
						this.data.class = new Gladiator();
						break;
				}
				
				for (var i = 0; i < this.Class.Buffs.length; i++) {
					this.Class.Buffs[i].on('levelchanged', function() {
						me.broadcast('selfbuffchanged');
					});
				}
				
				this.broadcast('classchanged');
			}
		}
	}
});

Object.defineProperty(Build.prototype, "Class", {
	get : function() {
		return this.data.class;
	}
});

Object.defineProperty(Build.prototype, "Hp", {
	get : function() {
		return this.data.baseStats.hp;
	},
	set : function(value) {
		if (value != undefined && value != '') {
			var value = parseInt(value);
			if (value != NaN) {
				this.data.baseStats.hp = value;
				this.broadcast('hpchanged');
			}
		}
	}
});

Object.defineProperty(Build.prototype, "Defense", {
	get : function() {
		return this.data.baseStats.defense;
	},
	set : function(value) {
		if (value != undefined && value != '') {
			var value = parseInt(value);
			if (value != NaN) {
				this.data.baseStats.defense = value;
				this.broadcast('defensechanged');
			}
		}
	}
});

Object.defineProperty(Build.prototype, "Dodge", {
	get : function() {
		return this.data.baseStats.dodge;
	},
	set : function(value) {
		if (value != undefined && value != '') {
			var value = parseInt(value);
			if (value != NaN) {
				this.data.baseStats.dodge = value;
				this.broadcast('dodgechanged');
			}
		}
	}
});

Object.defineProperty(Build.prototype, "Parry", {
	get : function() {
		return this.data.baseStats.parry;
	},
	set : function(value) {
		if (value != undefined && value != '') {
			var value = parseInt(value);
			if (value != NaN) {
				this.data.baseStats.parry = value;
				this.broadcast('parrychanged');
			}
		}
	}
});

Object.defineProperty(Build.prototype, "Block", {
	get : function() {
		return this.data.baseStats.block;
	},
	set : function(value) {
		if (value != undefined && value != '') {
			var value = parseInt(value);
			if (value != NaN) {
				this.data.baseStats.block = value;
				this.broadcast('blockchanged');
			}
		}
	}
});

Object.defineProperty(Build.prototype, "BlockAmount", {
	get : function() {
		return this.data.baseStats.blockAmount;
	},
	set : function(value) {
		if (value != undefined && value != '') {
			var value = parseInt(value);
			if (value != NaN) {
				this.data.baseStats.blockAmount = value;
				this.broadcast('blockamountchanged');
			}
		}
	}
});

Object.defineProperty(Build.prototype, "Monster", {
	get : function() {
		return this.data.monster;
	}
});
